package com.recruit.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.recruit.common.CurPool;
import com.recruit.common.LocalUser;
import com.recruit.common.util.ObserverGenerate;
import com.recruit.common.util.SingleUtil;
import com.recruit.dto.user.ChangePasswordDTO;
import com.recruit.dto.user.LoginDTO;
import com.recruit.dto.user.RegisterDTO;
import com.recruit.dto.user.UpdateInfoDTO;
import com.recruit.mapper.UserGroupMapper;
import com.recruit.model.GroupDO;
import com.recruit.model.UserDO;
import com.recruit.model.UserGroupDO;
import com.recruit.service.GroupService;
import com.recruit.service.UserIdentityService;
import com.recruit.service.UserService;
import com.recruit.vo.CreatedVO;
import com.recruit.vo.UnifyResponseVO;
import com.recruit.vo.UpdatedVO;
import com.recruit.vo.UserInfoVO;
import com.recruit.vo.UserPermissionVO;
import io.github.talelin.autoconfigure.exception.NotFoundException;
import io.github.talelin.autoconfigure.exception.ParameterException;
import io.github.talelin.core.annotation.LoginRequired;
import io.github.talelin.core.annotation.PermissionModule;
import io.github.talelin.core.annotation.RefreshRequired;
import io.github.talelin.core.token.DoubleJWT;
import io.github.talelin.core.token.Tokens;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author DHF
 */
@RestController
@RequestMapping("/recruit/user")
@PermissionModule(value = "用户")
@Validated
@Api(tags = "用户操作接口")
@Slf4j
public class UserController {

    @Resource
    private UserService userService;

    @Resource
    private GroupService groupService;

    @Resource
    private UserIdentityService userIdentityService;

    @Resource
    private UserGroupMapper userGroupMapper;

    @Resource
    private DoubleJWT jwt;

    /**
     * 用户注册
     */
    @PostMapping("/register")
    @ApiOperation(value = "用户注册")
    public CreatedVO register(
            @ApiParam(value = "注册信息实体", required = true)
            @RequestBody @Validated RegisterDTO validator) {
        userService.createUser(validator);
        // 用户注册成功，创建一个该用户对应的观察者类
        ObserverGenerate.generate(validator.getUsername());
        return new CreatedVO(11);
    }

    @PostMapping("/sendCode")
    @ApiOperation(value = "发送验证码")
    public UnifyResponseVO sendCode(@RequestBody @ApiParam(value = "电话号码", required = true) String tel) {
        if(Boolean.FALSE.equals(userService.sendCode(tel))){
            return new UnifyResponseVO(100,"发送失败");
        }
        return new UnifyResponseVO(200,"发送成功");
    }

    /**
     * 用户登陆
     */
    @PostMapping("/login")
    @ApiOperation(value = "用户登陆")
    public Tokens login(
            @ApiParam(value = "登录实体信息", required = true)
            @RequestBody @Validated LoginDTO validator) {
        UserDO user = userService.getUserByUsername(validator.getUsername());
        if (user == null) {
            throw new NotFoundException(10021);
        }
        boolean valid = userIdentityService.verifyUsernamePassword(user.getId(), user.getUsername(),
                                                                   validator.getPassword());
        if (!valid) {
            throw new ParameterException(10031);
        }
        // 保存当前登录用户到SingleUtil工具类中
        SingleUtil.userDO = user;
        LocalUser.setLocalUser(user);
        CurPool.curUserPool.put(user.getUsername(), user);
        return jwt.generateTokens(user.getId());
    }

    /**
     * 用户注销
     */
    @PostMapping("/loginOut")
    @ApiOperation(value = "用户注销")
    public UnifyResponseVO loginOut(@ApiParam(value = "注销用户名", required = true) @RequestBody String userName) {
        if (StringUtils.isNotBlank(userName)) {
            CurPool.curUserPool.remove(userName);
            UserDO user = userService.getUserByUsername(userName);
            CurPool.sessionPool.remove(user.getId());
            CurPool.webSockets.remove(user.getId());
            log.info("注销成功");
        }
        return new UnifyResponseVO();
    }

    /**
     * 更新用户信息
     */
    @PutMapping
    @LoginRequired
    @ApiOperation(value = "更新用户信息")
    public UpdatedVO update(
            @ApiParam(value = "用户更新实体信息", required = true) @RequestBody @Validated UpdateInfoDTO validator) {
        userService.updateUserInfo(validator);
        ObserverGenerate.observerUpdate(validator.getUsername());
        return new UpdatedVO(6);
    }

    /**
     * 修改密码
     */
    @PutMapping("/change_password")
    @LoginRequired
    @ApiOperation(value = "修改密码")
    public UpdatedVO updatePassword(
            @ApiParam(value = "修改密码实体", required = true)
            @RequestBody @Validated ChangePasswordDTO validator) {
        userService.changeUserPassword(validator);
        return new UpdatedVO(4);
    }

    /**
     * 刷新令牌
     */
    @GetMapping("/refresh")
    @RefreshRequired
    @ApiOperation(value = "刷新令牌")
    public Tokens getRefreshToken() {
        UserDO user = LocalUser.getLocalUser();
        return jwt.generateTokens(user.getId());
    }

    /**
     * 查询拥有权限
     */
    @GetMapping("/permissions")
    @LoginRequired
    @ApiOperation(value = "查询拥有权限")
    public UserPermissionVO getPermissions() {
        UserDO user = LocalUser.getLocalUser();
        boolean admin = groupService.checkIsRootByUserId(user.getId());
        List<Map<String, List<Map<String, String>>>> permissions = userService.getStructuralUserPermissions(
                user.getId());
        UserPermissionVO userPermissions = new UserPermissionVO(user, permissions);
        userPermissions.setAdmin(admin);
        return userPermissions;
    }

    /**
     * 查询用户角色
     */
    @GetMapping("/getGroup/{id}")
    @LoginRequired
    @ApiOperation(value = "查询用户角色")
    public int getUserGroup(
            @ApiParam(value = "角色id", required = true)
            @PathVariable Integer id) {
        LambdaQueryWrapper<UserGroupDO> queryWrapper = new QueryWrapper<UserGroupDO>().lambda();
        queryWrapper.eq(UserGroupDO::getUserId, id);
        UserGroupDO userGroupDO = userGroupMapper.selectOne(queryWrapper);
        return userGroupDO.getGroupId();
    }

    /**
     * 查询自己信息
     */
    @LoginRequired
    @GetMapping("/information")
    @ApiOperation(value = "查询自己信息")
    public UserInfoVO getInformation() {
        UserDO user = LocalUser.getLocalUser();
        List<GroupDO> groups = groupService.getUserGroupsByUserId(user.getId());
        return new UserInfoVO(user, groups);
    }

    /**
     * 获取所有用户
     */
    @GetMapping("/allUser")
    @ApiOperation(value = "获取所有用户对象")
    public List<UserInfoVO> allUserInfo(){
        return userService.allUser();
    }
}
